#include "MefoolDeviceManager.h"
#include "MefoolImageConverter.h"
#include <stdio.h>
#include <assert.h>
#include <windows.h>
#include <sstream>
#include <fstream>

bool writeImageAsRaw( const Mefool::Image& image, const char* filename )
{
	std::ofstream stream( filename, std::ios::binary|std::ios::out );
	if ( stream.is_open() )
	{
		stream.write( reinterpret_cast<const char*>( image.getBuffer().getBytes() ), image.getBuffer().getSizeInBytes() );
		if ( stream.fail() )
			return false;
	}
	return true;
}

bool writeRGB24ImageAsPPM( const Mefool::Image& image, const char* filename )
{
	if ( image.getFormat().getEncoding()!=Mefool::ImageFormat::RGB24 )
		return false;
	
	const Mefool::ImageFormat& imageFormat = image.getFormat();
	const Mefool::MemoryBuffer& imageBuffer = image.getBuffer();

	// Open file and write
	std::ofstream stream( filename, std::ios::binary|std::ios::out );
	if ( stream.is_open() )
	{
		stream << "P6 " << imageFormat.getWidth() << " " << imageFormat.getHeight() << " 255\n";
		if ( stream.fail() )
			return false;
		stream.write( reinterpret_cast<const char*>(imageBuffer.getBytes()), imageBuffer.getSizeInBytes() );
		if ( stream.fail() )
			return false;
	}		
	return true;
}

bool writeImageAsPPM( const Mefool::Image& image, const char* filename )
{
	Mefool::ImageConverter converter( Mefool::ImageFormat( image.getFormat().getWidth(), image.getFormat().getHeight(), Mefool::ImageFormat::RGB24 ) );
	if ( !converter.update( image ) )
		return false;
	return writeRGB24ImageAsPPM( converter.getImage(), filename );
}

void testDeviceCaptureSettings( Mefool::Device* device, std::size_t index )
{
	const Mefool::CaptureSettingsList& settingsList = device->getSupportedCaptureSettings();
	const Mefool::CaptureSettings& settings = settingsList[index];
	printf("\t%s", settings.toString().c_str() );
	
	if ( !device->startCapture( index ) )
	{
		printf(" Failed\n");
		return;
	}

	std::stringstream stream;
	Mefool::ImageFormat format = settings.getImageFormat();
	stream << device->getName() << "_" << index << "_" << format.getWidth() << "x" << format.getHeight() << "." << format.getEncodingName();
	std::string filename = stream.str();
	stream << ".PPM";
	std::string filenamePPM = stream.str();

	const Mefool::CapturedImage* capturedImage = NULL;
	do
	{
		device->update();
		capturedImage = device->getCapturedImage();
		Sleep(100);
		printf( "." );
	} 
	while ( !capturedImage || capturedImage->getSequenceNumber()< 5 );

	if ( capturedImage )
	{
		const Mefool::Image& image = capturedImage->getImage();
		writeImageAsRaw( image, filename.c_str() );
		writeImageAsPPM( image, filenamePPM.c_str() );
	}
	
	printf(" OK\n");
	device->stopCapture();
}

void testDevice( const Mefool::DeviceManager* deviceManager, std::size_t index )
{
	const Mefool::Devices& devices = deviceManager->getDevices();
	Mefool::Device* device = devices[index];
	
	printf("Device %d - %s\n", index, device->getName().c_str() );
	const Mefool::CaptureSettingsList& supportedSettings = device->getSupportedCaptureSettings();
	for ( std::size_t i=0; i<supportedSettings.size(); ++i )
	{
		testDeviceCaptureSettings( device, i );
		Sleep(100);
	}
}

int main()
{
	Mefool::DeviceManager* deviceManager = new Mefool::DeviceManager();
	deviceManager->update();

	const Mefool::Devices& devices = deviceManager->getDevices();
	for ( std::size_t i=0; i<devices.size(); ++i )
		testDevice( deviceManager, i );
	
	delete deviceManager;
	deviceManager = NULL;

	return 0;
}